package server

import (
	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-kratos/kratos/v2/middleware/tracing"
	"github.com/go-kratos/kratos/v2/transport/http"
	"github.com/gorilla/handlers"
	helloworld_v1 "kratosRecoverPanic/api/helloworld/v1"
	recover_v1 "kratosRecoverPanic/api/recover/v1"
	"kratosRecoverPanic/internal/conf"
	"kratosRecoverPanic/internal/service"
	"kratosRecoverPanic/pkg/kratos_encoder"
	"kratosRecoverPanic/pkg/kratos_middleware"
)

// NewHTTPServer new an HTTP server.
func NewHTTPServer(
	c *conf.Server,
	greeter *service.GreeterService,
	recoverSrv *service.RecoverService,
	ginSrv *service.GinService,
	logger log.Logger,
) *http.Server {
	var opts = []http.ServerOption{
		/***/
		// success resp: 有读取请求头中的traceId的操作
		http.ResponseEncoder(kratos_encoder.RespEncoder),
		// err resp: 有读取请求头中的traceId的操作
		http.ErrorEncoder(kratos_encoder.ErrorEncoder),

		http.Middleware(
			tracing.Server(),                 // Notice 必须把它写到 kratos_middleware.Server(logger) 前面 才能生成正常的traceId
			kratos_middleware.Server(logger), // Notice 自己写的中间件: 请求头加上traceId、在日志中打印请求的信息...

			// Notice 自定义的Recover中间件: 优点是可以将错误栈信息加到trace中方便排查问题
			kratos_middleware.RecoverMiddleware(),

			//recovery.Recovery(), // kratos自带的 Recover 中间件: 虽然能捕获panic但是找错误栈不方便！
		),
		/***/

		// Notice 跨域配置: github.com/gorilla/handlers
		http.Filter(handlers.CORS(
			handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type", "Authorization", "clan_auth_token"}),
			handlers.AllowedMethods([]string{"GET", "POST", "PUT", "HEAD", "OPTIONS"}),
			handlers.AllowedOrigins([]string{"*"}),
		)),
	}
	if c.Http.Network != "" {
		opts = append(opts, http.Network(c.Http.Network))
	}
	if c.Http.Addr != "" {
		opts = append(opts, http.Address(c.Http.Addr))
	}
	if c.Http.Timeout != nil {
		opts = append(opts, http.Timeout(c.Http.Timeout.AsDuration()))
	}

	srv := http.NewServer(opts...)

	/***/
	helloworld_v1.RegisterGreeterHTTPServer(srv, greeter) // helloworld kratos http server
	recover_v1.RegisterRecoverHTTPServer(srv, recoverSrv) // recoverSrv kratos http server

	// Notice 单独注册的路由中发生了panic不会被Recover中间件捕获到～middleware只服务于 proto service！
	srv.HandleFunc("/api/single-handler", recoverSrv.KratosSingleHandler)
	/***/

	/**/
	// Notice 注册gin引擎的http服务～用gin引擎的话记得把上面有关 kratosHttp 的代码注释掉！
	//ginRouter := gin.New()
	//ginRouter.Use(
	//	//gin.Recovery(), // TODO 这个中间件不生效！现在暂时把Recover的逻辑写在了每个Service中了！
	//	otelgin.Middleware(c.Name),
	//	// 中间件
	//	kGin.Middlewares(
	//		kratos_middleware.Server(logger), // Notice 使用自定义的Server中间件，将trace加到请求头中
	//	),
	//)
	//ginRouter.NoRoute(gin_encoder.NoRouteHandler)
	//ginRouter.NoMethod(gin_encoder.NoRouteHandler)
	//
	//// 在这里初始化GinService的路由
	//ginSrv.NewServiceRoutes(ginRouter.Group(ginSrv.GetPrefix()))
	//// Notice 使用gin引擎的路由的话，需要把上面 kratosHttp 的配置删掉，一定要记得加上下面这段！
	//srv.HandlePrefix("/", ginRouter)
	/**/

	return srv
}
